package me.sealer.ssm.token;

import me.sealer.ssm.constant.ErrorCodeConstant;
import me.sealer.ssm.exception.SsmException;

import java.io.Serializable;
import java.security.SecureRandom;
import java.util.LinkedList;
import java.util.Random;

/**
 * 功能描述： $ TokenList
 *
 * @author sealer
 * @email 1178884049@qq.com
 * @date 2019年12月02日 12时23分32秒
 */
public class TokenList implements Serializable {
    private static final long serialVersionUID = 3755604975447136421L;
    /**
     * token过期时间， 单位 s (秒)
     */
    private int delayTime;

    /**
     * list最大长度， 超过此长度， remove最早的一个token
     */
    private int maxEntryNumber;

    /**
     * token字符长度
     */
    private int tokenLength;

    /**
     * token串中的字符库
     */
    private char[] chars;

    /**
     * 此处用LinkedList， 原因是会频繁地插入删除操作
     */
    private final LinkedList<Token> tokenLinkedList = new LinkedList<>();

    private static Random randomNumberGenerator = new SecureRandom();

    public TokenList(int maxEntryNumber, int delayTime, int tokenLength, char[] chars) {
        this.maxEntryNumber = maxEntryNumber;
        this.delayTime = delayTime;
        this.tokenLength = tokenLength;
        this.chars = chars;
    }

    @Override
    public String toString() {
        return super.getClass().getName() + " :" + this.tokenLinkedList;
    }

    public String getNextTokenId() {
        // token字符资源库的size
        int charsLength = this.chars.length;

        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < this.tokenLength; ++i) {
            int index = randomNumberGenerator.nextInt(charsLength);
            sb.append(this.chars[index]);
        }

        return sb.toString();
    }

    public void add(Token item) {
        synchronized (this.tokenLinkedList) {
            this.tokenLinkedList.addLast(item);
            if (this.tokenLinkedList.size() > this.maxEntryNumber) {
                this.tokenLinkedList.removeFirst();
            }
        }
    }

    public Token get(String uniqueId, boolean ignoreCase) {
        synchronized (this.tokenLinkedList) {
            for (int i = 0; i < this.tokenLinkedList.size(); ++i) {
                Token item = this.tokenLinkedList.get(i);
                boolean result = ignoreCase ? item.getUniqueId().equalsIgnoreCase(uniqueId) : item.getUniqueId().equals(uniqueId);
                if (!result) {
                    continue;
                }
                long x = System.currentTimeMillis() - item.getCreateDate();
                if (x > this.delayTime * 1000) {
                    this.tokenLinkedList.remove(i);
                    throw new SsmException(ErrorCodeConstant.SYSTEM_TIME_OUT, new Object[]{"Image Verify Code "});
                }

                this.tokenLinkedList.remove(i);
                return item;
            }

            return null;
        }
    }
}
